/**
 * \file log.c
 * \author H4201
 */

/* MODULES USED */
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <pthread.h>

#include "../interface/messqueue.h"
#include "../utils/utils.h"
#include "log.h"

/*EXPORTED FUNCTIONS*/

/**
 * Fonction qui sert de point d'entrée au thread "Ecriture journal"
 * \param parameter inutilisé ici
 */
void* ecriture_journal (void *parameter) {
    (void) parameter;
    mqd_t balMessage = ouvrir_mqueue(BAL_MESSAGES_NAME, O_RDONLY);
    mqd_t balSuperviseur = ouvrir_mqueue(BAL_SUPERVISEUR_NAME, O_WRONLY);
    
    message_t unMessage;
    
    int bon = 1; // Prend la valeur 0 si on reçoit le message d'arrêt
    int retour;

    while (bon) {
        retour = lire_message(balMessage, &unMessage);
        if (retour >0) {
	    
            bon = ecrire_mes(unMessage);
	    
            mq_send(balSuperviseur,(char *) &unMessage,sizeof(message_t), 1); 
	
        } else {
            printf("erreur à la lecture d'un message dans bal_messsages.\n");
        }
    }

    pthread_exit(0);
}

/**
 * Ecrit le message dans le fichier de log
 * \param message Message à écrire dans le fichier de log
 * \return 0 si le message est un message d'arret, 1 sinon
 */
int ecrire_mes (message_t message) {

    time_t secondes;
    struct tm instant;
    
    time(&secondes);
    instant=*localtime(&secondes);
    FILE *log = fopen("log.txt", "a+");
    if ( log != NULL ) {
    
	//écriture de la date
    char * heures_txt = traduction_heure(instant.tm_hour);
    char * minutes_txt = traduction_heure(instant.tm_min);
    char * secondes_txt = traduction_heure(instant.tm_sec);
    fprintf(log, "\nLe %d/%d/%d à %s:%s:%s\n", instant.tm_mday, instant.tm_mon + 1, 1900 + instant.tm_year, heures_txt, minutes_txt, secondes_txt);
    free(heures_txt);
    free(minutes_txt);
    free(secondes_txt);
	
	switch (message.type)
	{
	    case AU : 
		fprintf(log,"Arrêt d'urgence !\n");
		break;
	    case ERRPIECE : 
		fprintf(log,"Pièce manquante !\n");
		break;
	    case ERRCARTON : 
		fprintf(log,"Carton absent !\n");
		break;
	    case ERRIMPR : 
		fprintf(log,"Imprimante défectueuse !\n");
		break;
	    case ERRDEFECT : 
		fprintf(log,"Trop de pièces défectueuses, seuil dépassé !\n");
		break;
	    case ERRFILE : 
		fprintf(log,"Trop de carton en attente pour la mise en palette !\n");
		break;
	    case ERRPALETTE : 
		fprintf(log,"Palette absente !\n");
		break;
	    case ERREMBAL : 
		fprintf(log,"Emballage défectueux !\n");
		break;
	    case ERRRETRAIT : 
		fprintf(log,"Retrait impossible !\n");
		break;
	    
	    
	    
	    case INIT : 
		fprintf(log,"Initialisation de la production.\n\
			    %d palettes de A, contenant chacune %d cartons, contenant chacun %d pièces de dimension %d.\n\
			    Le seuil d'erreur de A est de %d et le numéro de lot est %d.\n\
			    %d palettes de A, contenant chacune %d cartons, contenant chacun %d pièces de dimension %d.\n\
			    Le seuil d'erreur de A est de %d et le numéro de lot est %d.\n\
			    Le code opérateur est %d\n.", message.params[0], message.params[1],message.params[2], message.params[4],
			    message.params[5],message.params[3],message.params[6],message.params[7],message.params[8],message.params[10],
			    message.params[11],message.params[9],message.params[12]); 
		break;
	    case GO : 
		fprintf(log,"Lancement de la production. \n");
		if (message.params[0] == 0) {
		    fprintf(log, "Production de pièces de type A.\n");
		} else {
		    fprintf(log, "Production de pièces de type B.\n");
		}
		break;
	    case ARRET : 
		fprintf(log,"Arrêt total du système.\n");
		fclose(log);
		return 0;
		break;
	    case ARRDEG : 
		fprintf(log,"Arrêt du système en mode dégradé.\n");
		break;
	    case IMPRIMER : 
		fprintf(log,"Envoi d'un carton plein vers l'imprimante\n\
			    numéro de lot : %d, numéro de carton : %d, nombre de pièces : %d, code opérateur : %d\n", 
		message.params[0],message.params[1],message.params[2], message.params[3]);
		if (message.params[4] == 0) {
		    fprintf(log, "Pièces de type A,");
		} else {
		    fprintf(log, "Pièces de type B,");
		}
		fprintf(log, "avec un taux d'erreur de %d.\n",message.params[5]);
		break;		
	    case EMPALETTER : 
		fprintf(log,"Envoi d'un carton imprimé vers la mise en palette.\n\
			    numéro de lot : %d, numéro de carton : %d,", message.params[0],message.params[1]);
		if (message.params[2] == 0) {
		    fprintf(log, "pièces de type : A.\n");
		} else {
		    fprintf(log, "pièces de type : B.\n");
		}
		break;
	    case STOCKER : 
		fprintf(log,"Envoi d'une palette vers le stockage.\n\
			    Numéro de lot : %d, numéro de palette : %d,", message.params[0],message.params[2]);
		if (message.params[1] == 0) {
		    fprintf(log, "pièces de type : A.\n");
		} else {
		    fprintf(log, "pièces de type : B.\n");
		}
		break;
	    case DEMRETRAIT : 
		fprintf(log,"Demande de retrait de commande.\n\
			    Nombre de palettes de A : %d.\n\
			    Nombre de palettes de B : %d.\n\
			    Quai d'expédition : %d.\n", message.params[0], message.params[1], message.params[2]);
		break;
	    case FINLOT : 
		fprintf(log,"Fin du lot en cours.\n\
			    Numéro de lot : %d,", message.params[0]);
		if (message.params[1] == 0) {
		    fprintf(log, "pièces de type : A.\n");
		} else {
		    fprintf(log, "pièces de type : B.\n");
		}
		break;
	    case STOCKOK : 
		fprintf(log,"Stockage réussi.\n\
			    Numéro de lot : %d, numéro de palette : %d,", message.params[0],message.params[2]);
		if (message.params[1] == 0) {
		    fprintf(log, "pièces de type : A.\n");
		} else {
		    fprintf(log, "pièces de type : B.\n");
		}
		break;
	    case RETRAITOK : 
		fprintf(log,"Retrait réussi.\n\
			    Nombre de palettes de A : %d.\n\
			    Nombre de palettes de B : %d.\n\
			    Quai d'expédition : %d.\n", message.params[0], message.params[1], message.params[2]);
		break;
	    case REPARERR : 
		fprintf(log,"Erreurs réparées.\n");
		break;
	    case REPRNORM : 
		fprintf(log,"Reprise normale de la production.\n");
		break;
	    case REPRSUPP : 
		fprintf(log,"Reprise de la production. Le carton en cours de remplissage a été évacué.\n");
		break;
	    case STOPLOT : 
		fprintf(log,"Arret du lot en cours.\n");
		break;
			
	    default : fprintf(log, "message de type inconnu !\n");
	}
	
	fclose(log);
    } else {
	printf("Erreur à l'ouverture du fichier de log\n");
    }
	
    
    
    return 1;
}

/**
 * Transforme un nombre à 1 ou 2 chiffres en nombre à 2 chiffres
 * \param nb Nombre à transformer
 * \return Nombre transformé
 */
char * traduction_heure(unsigned int nb) {
    //char * texte = strdup("00");
    char * texte = malloc(3*sizeof(char));
    if (nb < 10) {
        snprintf(texte, 3, "0%d", nb);
    } else {
        snprintf(texte, 3, "%d", nb);    
    }
    
    return texte;
}
